<!DOCTYPE HTML>
<HTML>
	<HEAD>
		<META HTTP-EQUIV="CACHE-CONTROL" CONTENT="NO-CACHE" />
		<META HTTP-EQUIV="PRAGMA" CONTENT="NO-CACHE" />
		<META HTTP-EQUIV="EXPIRES" CONTENT="0" />
		<META HTTP-EQUIV="CONTENT-TYPE" CONTENT="text/html; charset=UTF-8" />
		<META HTTP-EQUIV="CONTENT-LANGUAGE" CONTENT="en,de" />
		<META NAME="ROBOTS" CONTENT="INDEX,NOFOLLOW" />
		<META NAME="AUTHOR" CONTENT="Andreas Kasch" />
		<META NAME="COPYRIGHT" CONTENT="&copy; 2013 Andreas Kasch" />
		<META NAME="DESCRIPTION" CONTENT="HTML5 Performance Optimizations" />
		<META NAME="KEYWORDS" CONTENT="HTML5, Performance" />
		
		<TITLE>HTML5 Performance Optimizations - Math.ceil</TITLE>
		
		<SCRIPT TYPE="text/javascript" CHARSET="utf-8" SRC="jquery-1.9.1.min.js"></SCRIPT>
	</HEAD>
	<BODY>
		<h1>Math.ceil</h1>
		<p>
			<input id="start1" type="button" value="Math.ceil"/>
			<input id="start2" type="button" value="Bit move"/>
			<input id="start3" type="button" value="Bit move (valid)"/>
			<input id="start4" type="button" value="Bit invert"/>
			<input id="start5" type="button" value="Bit invert (valid)"/>
		</p>
		<pre id="debug1"></pre>
		<pre id="debug2"></pre>
		<pre id="debug3"></pre>
		<pre id="debug4"></pre>
		<pre id="debug5"></pre>
		<script type="text/javascript">
			var CYCLES = 10000000;
			
			var measure = function(fn, randfn){
				var time = new Date().getTime();
				for(var i = 0; i < CYCLES; i++){
					var ceil = fn(randfn());
				}
				time = new Date().getTime() - time;
				return "\n\tTime: " + time/1000;
			}
			
			var checkAgainst = function(fn, fn2, randfn){
				var pos = true;
				var neg = true;
				for(var i = 0; i < 100; i++){
					var rand = randfn();
					var a = fn(rand);
					var b = fn2(rand);
					if(a != b) pos = false;
					a = fn(a);
					b = fn2(b);
					if(a != b) pos = false;
					a = fn(-rand);
					b = fn2(-rand);
					if(a != b) neg = false;
					a = fn(a);
					b = fn2(b);
					if(a != b) neg = false;
				}
				return "\n\tpositive numbers: " + ((pos)? "valid" : "invalid")
					+ "\n\tnegative numbers: " + ((neg)? "valid" : "invalid");
			}
			
			$("#start1").click(function(){
			
				var result = "Math.ceil:";
				result += measure(math, getRandom);
				
				$("#debug1").html(result);
			
			});
			
			$("#start2").click(function(){
			
				var result = "\nBit move";
				result += measure(bitmovneg, getRandom);
				result += checkAgainst(math, bitmovneg, getRandom);
				
				$("#debug2").html(result);
			
			});
			
			
			$("#start3").click(function(){
			
				var result = "\nBit move (valid)";
				result += measure(bitmov, getRandom);
				result += checkAgainst(math, bitmov, getRandom);
			
				$("#debug3").html(result);
			
			});
			
			
			$("#start4").click(function(){
			
				var result = "\nBit invert";
				result += measure(bitinvneg, getRandom);
				result += checkAgainst(math, bitinvneg, getRandom);
				
				$("#debug4").html(result);
			
			});
			
			$("#start5").click(function(){
			
				var result = "\nBit invert (valid)";
				result += measure(bitinv, getRandom);
				result += checkAgainst(math, bitinv, getRandom);
				
				$("#debug5").html(result);
			
			});
			
			var getRandom = function(){
				return Math.random()*10000000;
			};
			
			var math = function(number){
				return Math.ceil(number);
			}
			
			var bitmov = function(number){
				return (number > 0 && number % 1 != 0)? (number<<0)+1 : number<<0;
			}
			
			var bitinv = function(number){
				return (number > 0 && number % 1 != 0)? (~~number)+1 : ~~number;
			}
						
			var bitmovneg = function(number){
				return -(-number<<0);
			}
			
			var bitinvneg = function(number){
				return -(~~-number);
			}
		</script>
	</BODY>
</HTML>